package com.ht.web360.base.config.web;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONUtil;
import com.ht.web360.base.dto.Res;
import com.ht.web360.base.dto.UserInfo.dto.UserInfoDto;
import com.ht.web360.base.enums.UserType;
import com.ht.web360.base.utils.ThreadLocalUtil;
import com.ht.web360.base.utils.TokenUtil;
import com.ht.web360.base.utils.interfaces.RequireUserType;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

/**
 * 基础拦截器，拦截基础用户
 */
public class BasicInterceptor implements HandlerInterceptor {
    public void sendErrorRes(HttpServletResponse response, String msg) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType(ContentType.JSON.getValue());
        try (
                OutputStream os = response.getOutputStream()
        ) {
            os.write(JSONUtil.toJsonStr(Res.fail(msg)).getBytes(StandardCharsets.UTF_8));
        }
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod handlerMethod) {
            RequireUserType annotation = handlerMethod.getMethodAnnotation(RequireUserType.class);
            UserType level;
            if (annotation == null) {
                level = UserType.Public;
            } else {
                level = annotation.value();
            }
            // 当前接口为公开接口
            if (level == UserType.Public) {
                return true;
            }

            // 当前接口不公开，需要通过 jwt 获取用户信息
            Cookie[] cookies = request.getCookies();
            String jwtToken = null;
            if (cookies == null) {
                // 如果没有Token，则拒绝访问
                sendErrorRes(response, "未登录，禁止访问");
                return false;
            }
            for (var cookie : cookies) {
                // 从 cookie 中获取token
                if ("token".equals(cookie.getName())) {
                    jwtToken = cookie.getValue();
                }
            }
            if (StrUtil.isBlank(jwtToken)) {
                // 如果没有Token，则拒绝访问
                sendErrorRes(response, "未登录，禁止访问");
                return false;
            }
            try {
                UserInfoDto userInfoDto = TokenUtil.getUser(jwtToken);
                if (userInfoDto == null || StrUtil.isBlankIfStr(userInfoDto.getId())) {
                    throw new RuntimeException();
                }
                // 判断当前用户是否有访问资格
                if (userInfoDto.getUserType() != null && userInfoDto.getUserType().getValue() >= level.getValue()) {
                    ThreadLocalUtil.setUserId(Long.parseLong(userInfoDto.getId()));
                    ThreadLocalUtil.setUserDto(userInfoDto);
                    return true;
                } else {
                    sendErrorRes(response, "权限不足，拒绝访问");
                    return false;
                }
            } catch (RuntimeException exception) {
                // token 解析错误，拒绝访问
                sendErrorRes(response, "token错误，拒绝访问，请重新登录");
                return false;
            }
        }
        return true; // 允许请求继续
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        response.setCharacterEncoding("utf-8");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ThreadLocalUtil.removeAll();
    }
}
